package xfuzzy.xfhl.model.hierStruct;

/**
 * Clase que representa un modulo difuso de 2 entradas 1 salida, implementa la
 * interfaz XfhlINode
 * 
 * @author Sergio Cala Cordero, Septiembre 2009, Herramienta XFHL
 * 
 */
public class XfhlModule extends XfhlAbstract implements XfhlINode {

	/**
	 * Identificador del modulo
	 */
	private int idMod;

	/**
	 * Entrada1
	 */
	private XfhlINode ent1;

	/**
	 * Entrada2
	 */
	private XfhlINode ent2;

	/**
	 * Salida
	 */
	private XfhlINode sal;

	/**
	 * 
	 */
	public XfhlModule() {
		this.idMod = -1;
		this.ent1 = null;
		this.ent2 = null;
		this.sal = null;
	}

	/**
	 * 
	 * @param sal
	 */
	public XfhlModule(XfhlModule sal) {
		this.idMod = -1;
		this.ent1 = null;
		this.ent2 = null;
		this.sal = sal;
	}

	/**
	 * 
	 * @param ent1
	 * @param ent2
	 * @param sal
	 * @param idMod
	 */
	public XfhlModule(XfhlINode ent1, XfhlINode ent2, XfhlINode sal, int idMod) {
		this.idMod = idMod;
		this.ent1 = ent1;
		this.ent2 = ent2;
		this.sal = sal;
	}

	/**
	 * GETTER AND SETTER
	 * 
	 */

	public int getIdMod() {
		return this.idMod;
	}

	public XfhlINode getEnt1() {
		return ent1;
	}

	public XfhlINode getEnt2() {
		return ent2;
	}

	public XfhlINode getSal() {
		return sal;
	}

	public void setIdMod(int idMod) {
		this.idMod = idMod;
	}

	public void setEnt1(XfhlINode ent1) {
		this.ent1 = ent1;
	}

	public void setEnt2(XfhlINode ent2) {
		this.ent2 = ent2;
	}

	public void setSal(XfhlINode sal) {
		this.sal = sal;
	}

	/**
	 * Nos dice si el modulo es vacio
	 * 
	 * @return true o false
	 */
	public boolean esVacio() {
		return this.sal == null;
	}

	/**
	 * Imprime por pantalla el XfhlModule
	 */
	public void imprime() {
		System.out.println();
		
		// Salida
		System.out.print("Salida: ");
		sal.imprime();
		
		// Entrada 1
		System.out.print("Entrada 1: ");
		ent1.imprime();

		// Entrada 2
		System.out.print("Entrada 2: ");
		ent2.imprime();
	}
	
	public String getDescripcion()  {
		
		String descripcion = "";
		if (ent1 != null)  {
			if (ent1 instanceof XfhlModule) 
				descripcion = "(" + ent1.getDescripcion() + ")";
			else
				descripcion = ent1.getDescripcion();
			descripcion += " + ";
		}
		else  {
			descripcion += " ? ";
		}
		if (ent2 != null)  {
			if (ent2 instanceof XfhlModule)
				descripcion += "(" + ent2.getDescripcion() + ")";
			else
				descripcion += ent2.getDescripcion();
			descripcion += " = ";
		}
		else
			descripcion += " ? ";
		if (sal != null)  {
			if (sal instanceof XfhlModule)
				descripcion += "(" + sal.getDescripcion() + ")";
			else
				descripcion += sal.getDescripcion();
		}
		else
			descripcion = " ? ";
		return descripcion;
	}
	

	/**
	 * copia un INodo
	 * 
	 * @return Devuelve un XfhlINode
	 */
	public XfhlINode copiar() {

		XfhlModule nuevo = new XfhlModule();

		nuevo.idMod = this.idMod;
		nuevo.sal = this.sal.copiar();
		nuevo.ent1 = this.ent1.copiar();
		nuevo.ent2 = this.ent2.copiar();

		return (XfhlINode) nuevo;
	}

	/**
	 * Metodo que nos permite copiar un XfhlNode o añadir un XfhlNode a un
	 * XfhlModule.
	 * 
	 * @param par
	 *            valor nos dice si estamos buscando un Modulo (0) o un Nodo (1)
	 *            MODULO (par=0): Copia un MODULO añadiendole un nuevo modulo
	 *            que es ent1 del modulo indicado, sus variables son sal= var+1,
	 *            ent2=var+2 y su id es idNuevoMod NODO (par=1): Copia un NODO
	 *            que va a convertirlo en modulo, donde sal es el valor del
	 *            Nodo, el idModulo es idNuevoMod, ent1 es var+1,ent2 es var+2.
	 * @param numMod
	 *            Numero de modulos del XfhlModule
	 * @param idNuevoMod
	 *            Identificador del nuevo modulo
	 */
	public XfhlINode copiar(int par, int numMod, int idNuevoMod) {

		XfhlModule nuevo = new XfhlModule();

		// Tenemos que ver si alguna entrada coincide con numMod
		// El modulo que buscamos es la entrada 1
		if (par == 0 && this.ent1 instanceof XfhlModule && ((XfhlModule) (this.ent1)).idMod == numMod) {
			// Nos creamos la variable interna
			XfhlNode nodeInner = new XfhlNode(idNuevoMod - 1, XfhlNode.INNER);
			// Nos creamos el nuevo nodo de entrada
			XfhlNode nodeInput = new XfhlNode(idNuevoMod, XfhlNode.INPUT);
			// Creamos el nuevo hijo izquierdo
			XfhlModule nEnt1 = new XfhlModule(this.ent1.copiar(), nodeInput, nodeInner, idNuevoMod);

			nuevo.idMod = this.idMod;
			nuevo.sal = this.sal.copiar();
			nuevo.ent1 = nEnt1;
			nuevo.ent2 = this.ent2.copiar();
		}
		// El modulo que buscamos es la entrada 2
		else if (par == 0 && this.ent2 instanceof XfhlModule && ((XfhlModule) (this.ent2)).idMod == numMod) {

			// Nos creamos la variable interna
			XfhlNode nodeInner = new XfhlNode(idNuevoMod - 1, XfhlNode.INNER);
			// Nos creamos el nuevo nodo de entrada
			XfhlNode nodeInput = new XfhlNode(idNuevoMod, XfhlNode.INPUT);
			// Creamos el nuevo hijo derecho
			XfhlModule nEnt2 = new XfhlModule(nodeInput, this.ent2.copiar(), nodeInner, idNuevoMod);

			nuevo.idMod = this.idMod;
			nuevo.sal = this.sal.copiar();
			nuevo.ent1 = this.ent1.copiar();
			nuevo.ent2 = nEnt2;
		} else {
			nuevo.idMod = this.idMod;
			nuevo.sal = this.sal.copiar(par, numMod, idNuevoMod);
			nuevo.ent1 = this.ent1.copiar(par, numMod, idNuevoMod);
			nuevo.ent2 = this.ent2.copiar(par, numMod, idNuevoMod);
		}

		return (XfhlINode) nuevo;
	}
}
